package fox.framework.rpc.endpoint.netty.server;

import fox.framework.rpc.common.StringUtils;
import fox.framework.rpc.converter.RpcMessageConverter;
import fox.framework.rpc.exception.RpcRuntimeException;
import fox.framework.rpc.message.MappedRpcHeader;
import fox.framework.rpc.message.RpcHeader;
import fox.framework.rpc.message.RpcMessageStatus;
import fox.framework.rpc.server.message.request.RpcAttribute;
import fox.framework.rpc.server.message.response.RpcServerResponse;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * @author cuichao
 * @Description: RpcEncodeServerResponse
 * @Date: create in 2021/2/20 21:18
 */
class RpcEncodeServerResponse implements RpcServerResponse {

    private String protocol;

    private int status = RpcMessageStatus.OK;

    private RpcHeader header = new MappedRpcHeader();

    private Object body;

    private byte[] bodySource;

    private RpcMessageConverter converter;

    private Map<String, Object> attributes = new HashMap<>(16);

    public RpcEncodeServerResponse(String protocol) {
        this.protocol = protocol;
    }

    /**
     * 编码
     */
    void decode() {
        if(converter == null){
            String msg = "the response encode miss some property: messageConverter or dataBinder";
            throw new RpcRuntimeException(msg);
        }
        //encode
        if(body == null){
            this.bodySource = new byte[0];
            this.header.setHeader(RpcHeader.CONTENT_LENGTH, Integer.toString(0));
        }else {
            byte[] bodySource = converter.encode(body);
            this.bodySource = bodySource;
            this.header.setHeader(RpcHeader.CONTENT_LENGTH, Integer.toString(bodySource.length));
        }

    }
    /**
     * 监听赋值属性时是否是编码属性
     *
     * @return
     */
    private boolean listenAttributeIsEncodeProperty(String name, Object value) {
        if (RpcAttribute.CONVERTER_NAME.equals(name) && assertInstance(value, RpcMessageConverter.class)) {
            converter = ((RpcMessageConverter) value);
            return true;
        }
        return false;
    }

    private boolean assertInstance(Object object, Class<?> cls) {
        if (cls.isInstance(object)) {
           return true;
        }
        return false;
    }

    /**
     * 获得编码后的body-source
     * @return
     */
    byte[] getBodySource(){
        return bodySource;
    }

    @Override
    public String getProtocol() {
        return protocol;
    }

    @Override
    public int getStatus() {
        return status;
    }

    @Override
    public void setHeader(String name, String value) {
        header.setHeader(name, value);
    }

    @Override
    public void setStatus(int status) {
        this.status = status;
    }

    @Override
    public void setContentType(String type) {
        header.setHeader(RpcHeader.CONTENT_TYPE, type);
    }

    @Override
    public void setEntityBody(Object body) {
        this.body = body;
    }

    @Override
    public String getContentType() {
        return header.getHeader(RpcHeader.CONTENT_TYPE);
    }

    @Override
    public String getHeader(String name) {
        return header.getHeader(name);
    }

    @Override
    public Collection<String> getHeaderNames() {
        return header.getHeaderNames();
    }



    @Override
    public void setAttribute(String name, Object value) {
        if (StringUtils.isEmpty(name) || value == null) {
            return;
        }
        if (!listenAttributeIsEncodeProperty(name, value)) {
            attributes.put(name, value);
        }
    }

    @Override
    public Object getAttribute(String name) {
        return attributes.getOrDefault(name,null);
    }
}
